canonical 제거법
아주 좋은 질문입니다. 기존 Tag 데이터에 canonicalTag가 없는 상태에서 마이그레이션을 하려면,
- 우선 nullable로 FK를 추가한 뒤,
- 기존 데이터를 처리하는 로직을 한 번 태워서 보완,
- 이후 nullable 제거하여 완성하는 방식이 이상적입니다.
✅ 요약: 단계별 전략 단계 설명 1단계 Prisma 모델에 canonicalTagId를 nullable하게 추가 2단계 기존 Tag 데이터를 기반으로 CanonicalTag 생성 + 연결 3단계 FK를 NOT NULL로 바꾸고 완전하게 만들기 (선택)
✅ 1단계: Prisma 모델 수정 (nullable) prisma 복사 편집 model Tag { id Int @id @default(autoincrement()) name String @unique canonicalTagId Int? // ✅ nullable canonical CanonicalTag? @relation(fields: [canonicalTagId], references: [id]) posts PostTag[] } Prisma 마이그레이션:
bash 복사 편집 npx prisma migrate dev --name add-canonical-tag-nullable ✅ 2단계: 기존 데이터를 처리하는 비즈니스 로직 실행 이 부분이 핵심입니다. 한 번만 실행해도 되는 로직이기 때문에, 다음 중 하나로 처리할 수 있습니다:
✅ 방법 A. 관리자용 마이그레이션 스크립트 작성 scripts/backfillCanonicalTags.ts
ts 복사 편집 import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient();
function normalize(name: string): string { return name.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, ""); }
async function run() { const tags = await prisma.tag.findMany({ where: { canonicalTagId: null } });
for (const tag of tags) { const normalized = normalize(tag.name);
let canonical = await prisma.canonicalTag.findUnique({
where: { normalizedName: normalized },
});
if (!canonical) {
canonical = await prisma.canonicalTag.create({
data: { normalizedName: normalized },
});
}
await prisma.tag.update({
where: { id: tag.id },
data: { canonicalTagId: canonical.id },
});
}
console.log("✅ 모든 태그의 canonical 연결 완료"); process.exit(); }
run().catch((e) => { console.error(e); process.exit(1); }); 실행:
bash 복사 편집 ts-node scripts/backfillCanonicalTags.ts ✅ 방법 B. 앱 부트 시 한 번만 실행 (임시) app.ts 또는 server.ts 내에서 await runBackfillIfNeeded() 실행
단, 이 방식은 배포 시점에 자동으로 처리되므로 위험하거나 예외처리를 잘 해둬야 함
✅ 3단계: nullable 제거 (완성) 모든 Tag에 canonicalTagId가 채워졌다면, 이제 다음과 같이 바꿀 수 있습니다:
prisma 복사 편집 canonicalTagId Int canonical CanonicalTag @relation(fields: [canonicalTagId], references: [id]) bash 복사 편집 npx prisma migrate dev --name make-canonical-tag-required ✅ 결론: "비즈니스 로직을 태워야 하나?" ✅ 예. 비즈니스 로직 수준의 스크립트를 한 번 태우는 것이 가장 안전하고 유지보수 가능한 방식입니다. 이 작업은 DB 레벨에서 처리하기 복잡하고, 의미 기준 정규화이기 때문에 앱 로직이 더 적합합니다.
필요하시면 이 스크립트를 CLI 툴처럼 만들거나, cron 작업으로 연동하는 방법도 안내해드릴 수 있습니다. 원하시나요?
0개의 댓글